package com.hundsun.epay.autosimu.codegen;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.hundsun.epay.autosimu.api.IntrospectedFieldControl;
import com.hundsun.epay.autosimu.api.IntrospectedTrade;
import com.hundsun.epay.autosimu.api.dom.OutputUtility;
import com.hundsun.epay.autosimu.api.dom.java.FullyQualifiedJavaType;
import com.hundsun.epay.autosimu.api.dom.java.Method;
import com.hundsun.epay.autosimu.api.dom.java.TopLevelClass;
import com.hundsun.epay.autosimu.enums.ControllerFieldType;
import com.hundsun.epay.autosimu.internal.ControlRespPackaging;
import com.hundsun.epay.autosimu.internal.ObligateInnerVariableName;
import com.hundsun.epay.autosimu.internal.rules.FieldControlRules;
import com.hundsun.epay.autosimu.internal.rules.RespControlRules;
import com.hundsun.epay.autosimu.internal.rules.Rules;
import com.hundsun.epay.autosimu.utils.StringUtility;

/**
 * 交易生成器
 * @author clown
 *
 */
public abstract class AbstractTradeGenerator extends AbstractGenerator {
	private IntrospectedTrade introspectedTrade;

	public IntrospectedTrade getIntrospectedTrade() {
		return introspectedTrade;
	}

	public void setIntrospectedTrade(IntrospectedTrade introspectedTrade) {
		this.introspectedTrade = introspectedTrade;
	}
	
	/**
	 * 统一处理字段控制提取代码
	 * 
	 * @param importTypes
	 * @param bodies
	 */
	protected void addDrawRespFieldExpression(Set<FullyQualifiedJavaType> importTypes, List<String> bodies){
		StringBuilder builder = new StringBuilder();
		
		//orderNo类型用作控制
		String fieldOrderNo = getIntrospectedTrade().getOrderNoControlField();
		if(fieldOrderNo != null){
			IntrospectedFieldControl introspectedField = introspectedChannel.getIntrospectedFieldControl(fieldOrderNo);
			addDrawRespFieldExpression(builder, introspectedField, importTypes, bodies);
		}
		
		//orderNo类型用作控制
		String fieldDetailNo = getIntrospectedTrade().getDetailNoControlField();
		if(fieldDetailNo != null){
			IntrospectedFieldControl introspectedField = introspectedChannel.getIntrospectedFieldControl(fieldDetailNo);
			addDrawRespFieldExpression(builder, introspectedField, importTypes, bodies);
		}
		
		//Controller 类型的当前控制配置
		Set<String> fieldControls = getIntrospectedTrade().getCurrentControlField();
		if(fieldControls != null){
			for (String controlIds : fieldControls) {
				List<IntrospectedFieldControl> introspectedFields = introspectedChannel.getActualIntrospectedFieldControl(controlIds);
				for (IntrospectedFieldControl introspectedField : introspectedFields) {
					addDrawRespFieldExpression(builder, introspectedField, importTypes, bodies);
				}
			}
		}
		//Ref 当前控制配置
		Set<String> refFieldControls = getIntrospectedTrade().getCurrentRefControlField();
		if(refFieldControls != null){
			for (String controlIds : refFieldControls) {
				List<IntrospectedFieldControl> introspectedFields = introspectedChannel.getActualIntrospectedFieldControl(controlIds);
				for (IntrospectedFieldControl introspectedField : introspectedFields) {
					addDrawRespFieldExpression(builder, introspectedField, importTypes, bodies);
				}
			}
		}
	}
	
	private void addDrawRespFieldExpression(StringBuilder builder, IntrospectedFieldControl introspectedField, Set<FullyQualifiedJavaType> importTypes, List<String> bodies){
		//仅对控制类型需要提取控制字段
//		if(!ControllerFieldType.CONTROLLER.equals(introspectedField.getFieldControlType())){
//			return;
//		}
		List<Rules> rules = introspectedField.getFieldControlRule();
		if(rules == null || rules.isEmpty()){
			return;
		}
		
		builder.setLength(0);
		//分隔
		String separator = introspectedField.getFieldControlSeparator();
		//使用分隔符
		if(StringUtility.stringHasValue(separator)){
			String attrName = introspectedField.getInnerVaribaleName() + "_array";
			builder.append("String [] ").append(attrName)
				.append(" = ").append(introspectedField.getInnerVaribaleName())
				.append(".split(\"").append(separator).append("\", -1);");
			bodies.add(builder.toString());
			//控制key存储
			int index = 0;
			for (Rules controlRule : rules) {
				builder.setLength(0);
				FieldControlRules fieldControlRule = (FieldControlRules) controlRule;
				builder.append("String ").append(fieldControlRule.getName()).append(" = ")
					.append(attrName).append("[").append(index).append("];");
				bodies.add(builder.toString());
				index ++;
			}
		}else{//使用字段位置截取
			String innerVariableName = introspectedField.getInnerVaribaleName();
			for (Rules controlRule : rules) {
				builder.setLength(0);
				FieldControlRules fieldControlRule = (FieldControlRules) controlRule;
				String controlRuleName = fieldControlRule.getName();
				builder.append("String ").append(controlRuleName).append(" = ").append(innerVariableName);
				if(fieldControlRule.getLength() == 0) {//截取长度等于0，表示不需要截取
					
					builder.append(";");
				}else {
					builder.append(".subString(");
					if(fieldControlRule.getOffset() < 0){
						builder.append(innerVariableName).append(".length() - ").append(Math.abs(fieldControlRule.getOffset()))
							.append(", ");
						int endIndex = fieldControlRule.getOffset() + fieldControlRule.getLength();
						if(endIndex < 0){
							builder.append(innerVariableName).append(".length() - ").append(Math.abs(endIndex));
						}else{
							builder.append(innerVariableName).append(".length()");
						}
					}else{
						builder.append(fieldControlRule.getOffset()).append(", ").append(fieldControlRule.getOffset() + fieldControlRule.getLength());
					}
					builder.append(");");
				}
				bodies.add(builder.toString());
			}
		}
//		bodies.add("");
	}
	
	/**
	 * 交易实现
	 * @param topClass
	 */
	public abstract void addTradeImplementsElements(TopLevelClass topClass);
	
	/**
	 * 返回请求参数提取器
	 * @return
	 */
	protected abstract AbstractRequestDataDrawer getAbstractRequestDataDrawer();
	
	/**
	 * 添加从数据库fields字段提取引用的请求数据
	 * @param importTypes
	 * @param method
	 * @return
	 */
	protected String addDrawRequestDataFromDBExpression(Set<FullyQualifiedJavaType> importTypes, Method method){
		String line;
		//查询库表
		line = "Orders " + ObligateInnerVariableName.OBLIGATE_ORDER_OBJECT + " = " + ObligateInnerVariableName.OBLIGATE_ORDER_SERVICE + ".findOrderByOrderNo(" + ObligateInnerVariableName.OBLIGATE_ORDER_NO + ");";
		method.addBodyLine(line);
		line = "String " + ObligateInnerVariableName.OBLIGATE_ORDER_FIELDS + " = " + ObligateInnerVariableName.OBLIGATE_ORDER_OBJECT + ".get(\"fields\");";
		method.addBodyLine(line);
		
		//解析控制字段
		line = "JSONObject " + ObligateInnerVariableName.OBLIGATE_FIELD_OBJECT + " = JSONObject.parseObject(" + ObligateInnerVariableName.OBLIGATE_ORDER_FIELDS + ");";
		method.addBodyLine(line);
		
		method.addBodyLine("");
		
		//从数据库字段提取控制数据
		Set<String> fieldIds = getIntrospectedTrade().getCurrentRefControlField();
		if(fieldIds != null){
			StringBuilder builder = new StringBuilder();
			List<String> innerVarNames = new ArrayList<String>();   //记录已声明的内部变量名，去除重复的key定义
			for (String fieldId : fieldIds) {
				List<IntrospectedFieldControl> fieldControls = getIntrospectedChannel().getActualIntrospectedFieldControl(fieldId);
				for (IntrospectedFieldControl fieldControl : fieldControls) {
					String innerVarName = fieldControl.getInnerVaribaleName();
					if(innerVarNames.contains(innerVarName)){
						continue;
					}
					builder.setLength(0);
					builder.append("String ").append(innerVarName).append(" = ").append(ObligateInnerVariableName.OBLIGATE_FIELD_OBJECT).append(".getString(\"").append(fieldControl.getInnerVaribaleName()).append("\");");
					method.addBodyLine(builder.toString());
					innerVarNames.add(innerVarName);
				}
			}
		}
		return ObligateInnerVariableName.OBLIGATE_FIELD_OBJECT;
	}
	
	/**
	 * 判断交易是否需要重定向到前台回调地址（根据交易类型，仅异步通知交易需要前台回调）,且前台回调，只能为ref引用
	 * @return
	 */
	protected boolean checkNeedRedirectFrontUrl(){
		Set<String> fieldIds = this.getIntrospectedTrade().getCurrentRefControlField();
		if(fieldIds == null || fieldIds.isEmpty()){
			return false;
		}
		for (String fieldId : fieldIds) {
			List<IntrospectedFieldControl> fieldControls = getIntrospectedChannel().getActualIntrospectedFieldControl(fieldId);
			for (IntrospectedFieldControl fieldControl : fieldControls) {
				if(ControllerFieldType.FRONTURL.equals(fieldControl.getFieldControlType())){
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * 组装单笔交易响应报文，主要根据响应条件，处理响应报文，替换关键字段,需要替换的响应字段为格式为：#respKey#
	 * @param importTypes
	 * @param method
	 */
	protected void assembleSingleTradeResp(String respMsg, Method method, int indent){
		String regex = "#([a-zA-Z0-9_-]+)#";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(respMsg);
		Map<String, String> replaceUnits = new HashMap<String, String>();
		while(matcher.find()){
			replaceUnits.put(matcher.group(0), matcher.group(1));
		}
		
		StringBuilder builder = new StringBuilder();
		OutputUtility.javaIndent(builder, indent);
		builder.append(ObligateInnerVariableName.OBLIGATE_TEMPLATE_RESPMSG).append(" = \"").append(respMsg).append("\";");
		method.addBodyLine(builder.toString());
		
		
		for (Entry<String, String> entry : replaceUnits.entrySet()) {
			builder.setLength(0);
			OutputUtility.javaIndent(builder, indent);
			builder.append(ObligateInnerVariableName.OBLIGATE_TEMPLATE_RESPMSG).append(".replaceAll(\"").append(entry.getKey()).append("\", ").append(entry.getValue()).append(");");
			method.addBodyLine(builder.toString());
		}
	}
	public static void main(String[] args) {
		String respMsg = "version=5.1.0&signMethod=01&encoding=UTF-8&merId=#merId#&orderId=#orderId#&queryId=UNIONPAY123456789&txnAmt=#txnAmt#&settleAmt=#txnAmt#&respCode=#respCode#&respMsg=惠付挡板模拟异步通知返回";
//		assembleSingleTradeResp(respMsg, null);
	}
	
	protected void assembleCheckSingleResp(Method method){
		List<ControlRespPackaging> packets = getIntrospectedTrade().getConditionalControlResp();
		StringBuilder builder = new StringBuilder();
		builder.append("String ").append(ObligateInnerVariableName.OBLIGATE_TEMPLATE_RESPMSG).append(";");
		method.addBodyLine(builder.toString());
		boolean first = true;
		int indent = 1;
		if(packets != null){
			for (ControlRespPackaging packet : packets) {
				builder.setLength(0);
				if(first){
					builder.append("if(");
					first = false;
				}else{
					builder.append("} else if(");
				}
				List<RespControlRules> rules = packet.getAndRules();
				for (RespControlRules rule : rules) {
					builder.append(rule.formatExpression());
					builder.append(" && ");
				}
				builder.setLength(builder.length() - 4);
				builder.append("){");
				method.addBodyLine(builder.toString());
				assembleSingleTradeResp(packet.getRespContent(), method, indent);
//				method.addBodyLine("}");
			}
		}

		ControlRespPackaging defaultPacket = getIntrospectedTrade().getDefaultControlResp();
		builder.setLength(0);
		if(first){//无条件响应项
			assembleSingleTradeResp(defaultPacket.getRespContent(), method, 0);
		}else{
			builder.append("} else {");
			method.addBodyLine(builder.toString());
			assembleSingleTradeResp(defaultPacket.getRespContent(), method, indent);
			method.addBodyLine("}");
		}
	}
}
